home *** CD-ROM | disk | FTP | other *** search
- #include "sysheaders.h"
- #include "cdpanel.h"
- #include "CompactPlayer.h"
-
- /********************************************************
- * SCSI
- */
-
- struct MsgPort *SCSIPort;
- struct IOStdReq *SCSIIO;
- STRPTR Device = "scsi.device";
- ULONG Unit = 6;
- UBYTE *DataBuf;
- UBYTE *TOCBuf;
- UBYTE *SenseData;
- BOOL Ejected = FALSE;
- BOOL JustStarted = FALSE;
-
- //#define SINGLE_TRACK_PLAY 1
-
- #define BLOCKSPERSECOND 75 /* CD blocks per second of audio */
-
- int __stdargs
- Open_SCSI(void)
- {
- if ((DataBuf = AllocVec(DATA_LEN, MEMF_CHIP | MEMF_CLEAR)) &&
- (TOCBuf = AllocVec(TOC_LEN, MEMF_CHIP)) &&
- (SenseData = AllocVec(SENSE_LEN, MEMF_CHIP | MEMF_CLEAR)) &&
- (SCSIPort = CreateMsgPort()) &&
- (SCSIIO = CreateIORequest(SCSIPort, sizeof(struct IOStdReq))) &&
- !OpenDevice(Device, Unit, (struct IORequest *) SCSIIO, NULL))
- {
- SCSIIO->io_Command = HD_SCSICMD;
-
- CD_Eject = Eject_SCSI;
- CD_Stop = Stop_SCSI;
- CD_Play = Play_SCSI;
- CD_PauseResume = PauseResume_SCSI;
- CD_Seek = Seek_SCSI;
- CD_Snoop = Snoop_SCSI;
- CD_ReadTOC = ReadTOC_SCSI;
- CD_IsCD = IsCD_SCSI;
- CD_Close = (void (*)(void))Close_SCSI;
-
- if (CD_IsCD())
- return 0;
- else
- ErrorMsg(GS(DEVICE_FAIL), Device, Unit);
- }
- else
- ErrorMsg(GS(SCSI_FAIL), Device, Unit);
- Close_SCSI();
- return -1;
- }
-
- void __stdargs
- Close_SCSI(void)
- {
- if (SCSIIO)
- {
- if (SCSIIO->io_Command == HD_SCSICMD)
- CloseDevice((struct IORequest *) SCSIIO);
- DeleteIORequest(SCSIIO);
- SCSIIO = NULL;
- }
- if (SCSIPort)
- {
- DeleteMsgPort(SCSIPort);
- SCSIPort = NULL;
- }
- if (SenseData)
- {
- FreeVec(SenseData);
- SenseData = NULL;
- }
- if (TOCBuf)
- {
- FreeVec(TOCBuf);
- TOCBuf = NULL;
- }
- if (DataBuf)
- {
- FreeVec(DataBuf);
- DataBuf = NULL;
- }
-
- CD_Eject = (void (*)(UBYTE))Dummy;
- CD_Stop = (void (*)(void))Dummy;
- CD_Play = (void (*)(ULONG))Dummy;
- CD_PauseResume = (void (*)(UBYTE))Dummy;
- CD_Seek = (void (*)(LONG))Dummy;
- CD_Snoop = (ULONG (*)(ULONG *, ULONG *, ULONG *, ULONG))Dummy;
- CD_ReadTOC = (ULONG (*)(void))Dummy;
- CD_IsCD = (BOOL (*)(void))Dummy;
- CD_Close = (void (*)(void))Dummy;
- }
-
- static int
- DoSCSI( APTR data, int dsize, APTR cmd, int csize, UBYTE flags )
- {
- if (SCSIIO)
- {
- static struct SCSICmd ScsiCmd;
-
- /* send a SCSI Direct command */
-
- ScsiCmd.scsi_Command = cmd;
- ScsiCmd.scsi_CmdLength = csize;
- ScsiCmd.scsi_Data = data;
- ScsiCmd.scsi_Length = dsize;
- ScsiCmd.scsi_SenseData = SenseData;
- ScsiCmd.scsi_SenseLength = SENSE_LEN;
- ScsiCmd.scsi_SenseActual = 0;
- ScsiCmd.scsi_Flags = flags;
-
- SCSIIO->io_Command = HD_SCSICMD;
- SCSIIO->io_Data = &ScsiCmd;
- SCSIIO->io_Length = sizeof(ScsiCmd);
-
- DoIO((struct IORequest *)SCSIIO);
-
- return SCSIIO->io_Error;
- }
- return -1;
- }
-
- void
- Eject_SCSI( UBYTE out )
- {
- static SCSICMD6 command = { SCSI_DA_START_STOP_UNIT };
-
- /* Eject/Reload a CD */
-
- command.b4 = out ? 0x02 : 0x03;
-
- Ejected = out;
-
- DoSCSI( NULL, 0, &command, sizeof(command), (SCSIF_READ|SCSIF_AUTOSENSE) );
- }
-
- void
- Stop_SCSI(void)
- {
- static SCSICMD6 command = { SCSI_DA_START_STOP_UNIT };
-
- /* Stop motor */
-
- DoSCSI( NULL, 0, &command, sizeof(command), (SCSIF_READ|SCSIF_AUTOSENSE) );
- }
-
- #ifndef SINGLE_TRACK_PLAY
- ULONG EndAddress = ~0;
- #endif
-
- void
- Play_SCSI(ULONG track)
- {
- static SCSICMD12 command = { SCSI_CD_PLAY_AUDIO_12 };
- ULONG address, length;
-
- /* Play a track. Basic program (random order) support in here, even
- * though there is no program editor yet. */
-
- if (TOCP[0] != ~0)
- {
- if (TOCP[track] == ~0)
- return;
- address = TOCL[TOCP[track-1]]+1;
- }
- else
- {
- if (track > Tracks)
- return;
- address = TOCL[track-1]+1;
- }
- Track = track;
-
- command.b2 = (address & 0xff000000) >> 24;
- command.b3 = (address & 0x00ff0000) >> 16;
- command.b4 = (address & 0x0000ff00) >> 8;
- command.b5 = (address & 0x000000ff);
-
- #ifdef SINGLE_TRACK_PLAY
- if (TOCP[0] != ~0)
- length = TOCL[TOCP[track]] - address - 1;
- else
- length = TOCL[Tracks-1] - address - 1;
-
- command.b6 = (length & 0xff000000) >> 24;
- command.b7 = (length & 0x00ff0000) >> 16;
- command.b8 = (length & 0x0000ff00) >> 8;
- command.b9 = (length & 0x000000ff);
- #else
- /* continuous play */
- if (TOCP[0] != ~0)
- EndAddress = TOCL[TOCP[track]] - 1;
- else
- EndAddress = ~0;
-
- command.b6 = 0xff;
- command.b7 = 0xff;
- command.b8 = 0xff;
- command.b9 = 0xff;
- #endif
-
- /* because a Toshiba XM3601B can abort a PLAY_AUDIO sent immediately
- * after media change without any error code, we have a kludge that makes
- * it restart. */
- JustStarted = TRUE;
-
- DoSCSI( DataBuf, DATA_LEN, &command, sizeof(command), (SCSIF_READ|SCSIF_AUTOSENSE) );
- }
-
- void
- PauseResume_SCSI( UBYTE pause )
- {
- static SCSICMD10 command = { SCSI_CD_PAUSE_RESUME };
-
- /* Pause/Restart playing */
-
- command.b8 = pause;
-
- DoSCSI( NULL, 0, &command, sizeof(command), (SCSIF_READ|SCSIF_AUTOSENSE) );
- }
-
- void
- Seek_SCSI( LONG seconds )
- {
- static SCSICMD10 command = { SCSI_CD_READ_SUB_CHANNEL };
-
- command.b2 = 0x40;
- command.b3 = 1;
- command.b6 = 0;
-
- command.b7 = 255;
- command.b8 = 255;
-
- /* Seek forward/backward (rewind/fast forward) */
-
- if (!DoSCSI( DataBuf, DATA_LEN, &command, sizeof(command), (SCSIF_READ|SCSIF_AUTOSENSE) ))
- {
- static SCSICMD12 command = { SCSI_CD_PLAY_AUDIO_12 };
-
- ULONG address = (DataBuf[8] << 24 | DataBuf[9] << 16 | DataBuf[10] << 8 | DataBuf[11]);
- ULONG length, start, end;
-
- address += seconds * BLOCKSPERSECOND;
-
- if (TOCP[0] != ~0)
- {
- start = TOCL[TOCP[Track-1]];
- end = TOCL[TOCP[Track]];
- }
- else
- {
- start = TOCL[Track-1];
- end = TOCL[Track];
- }
-
- if (address >= start && address < end)
- {
- command.b2 = (address & 0xff000000) >> 24;
- command.b3 = (address & 0x00ff0000) >> 16;
- command.b4 = (address & 0x0000ff00) >> 8;
- command.b5 = (address & 0x000000ff);
-
- #ifdef SINGLE_TRACK_PLAY
- length = end - address - 1;
-
- command.b6 = (length & 0xff000000) >> 24;
- command.b7 = (length & 0x00ff0000) >> 16;
- command.b8 = (length & 0x0000ff00) >> 8;
- command.b9 = (length & 0x000000ff);
- #else
- command.b6 = 0xff;
- command.b7 = 0xff;
- command.b8 = 0xff;
- command.b9 = 0xff;
- #endif
-
- DoSCSI( DataBuf, DATA_LEN, &command, sizeof(command), (SCSIF_READ|SCSIF_AUTOSENSE) );
- }
- }
- }
-
- ULONG
- Snoop_SCSI(ULONG *track, ULONG *tracktime, ULONG *time, ULONG ostat)
- {
- static SCSICMD10 command = { SCSI_CD_READ_SUB_CHANNEL };
-
- command.b2 = 0x40;
- command.b3 = 1;
- command.b6 = 0;
-
- command.b7 = 255;
- command.b8 = 255;
-
- /* snoop and update current status */
-
- if (!DoSCSI( DataBuf, DATA_LEN, &command, sizeof(command), (SCSIF_READ|SCSIF_AUTOSENSE) ))
- {
- ULONG status;
- ULONG address;
-
- address = (DataBuf[8] << 24 | DataBuf[9] << 16 | DataBuf[10] << 8 | DataBuf[11]);
-
- if (DataBuf[1] == 0x11)
- {
- #ifndef SINGLE_TRACK_PLAY
- if (address >= EndAddress)
- {
- CD_Play(Track + 1); /* end of track, continue program */
- return CD_Snoop(track, tracktime, time, CDP_STOPPED);
- }
- #endif
- status = CDP_PLAYING;
- }
- else
- if (DataBuf[1] == 0x12)
- status = CDP_PAUSED;
- else
- {
- if (JustStarted && !(DataBuf[5] & 0x04 /* signifies a data track */))
- {
- /* kludge for aborted PLAY_AUDIO (needed with Toshiba XM3601B) */
- CD_Play(Track); /* restart track */
- return CD_Snoop(track, tracktime, time, CDP_STOPPED);
- }
- else
- if (ostat == CDP_PLAYING)
- {
- CD_Play(Track + 1); /* end of track, continue */
- return CD_Snoop(track, tracktime, time, CDP_STOPPED);
- }
- JustStarted = FALSE;
- *track = Track = 0;
- return CDP_STOPPED;
- }
-
- Track = *track = DataBuf[6];
-
- *time = address / BLOCKSPERSECOND;
-
- address = (DataBuf[12] << 24 | DataBuf[13] << 16 | DataBuf[14] << 8 | DataBuf[15]);
-
- *tracktime = address / BLOCKSPERSECOND;
-
- if (*tracktime > 1) /* if the player managed to stay on for longer than */
- JustStarted = FALSE; /* one second, we can assume it will do so. */
-
- return status;
- }
- return (ULONG)(Ejected ? CDP_EJECTED : CDP_EMPTY);
- }
-
- ULONG
- ReadTOC_SCSI(void)
- {
- static SCSICMD10 command = { SCSI_CD_READ_TOC };
-
- command.b7 = 0x03;
- command.b8 = 0x24;
-
- /* Read track lengths from the CD Table Of Contents */
-
- if (!DoSCSI( TOCBuf, TOC_LEN, &command, sizeof(command), (SCSIF_READ|SCSIF_AUTOSENSE) ))
- {
- ULONG tocsize = (TOCBuf[0] << 8) | TOCBuf[1];
- ULONG tracks = 0;
- UBYTE *toc;
-
- if (tocsize > 2) tocsize -= 2;
-
- for (toc = &TOCBuf[4] ; toc < (&TOCBuf[4] + tocsize) ; toc += 8 )
- {
- TOCL[tracks] = (toc[4] << 24) | (toc[5] << 16) | (toc[6] << 8) | (toc[7]);
- TOCT[tracks] = TOCL[tracks] / BLOCKSPERSECOND;
- TOCF[tracks] = (toc[1] & 0x04) ? 1 : 0;
- TOCS[tracks] = &TitleBuffer[(tracks+2)*40];
- Sprintf(TOCS[tracks], GS(TRACK_NUM), tracks+1);
- tracks++;
- }
- TOCS[--tracks] = NULL;
-
- if (!GetIndex( tracks, TOCL[2], TOCL[tracks]))
- {
- TITLE[0] = NULL;
- TITLE[1] = NULL;
- }
-
- if (!TITLE[0])
- {
- TITLE[0] = &TitleBuffer[0];
- strcpy(TITLE[0], GS(UNKNOWN_ARTIST));
- }
-
- if (!TITLE[1])
- {
- TITLE[1] = &TitleBuffer[40];
- strcpy(TITLE[1], GS(UNKNOWN_TITLE));
- }
-
- return tracks;
- }
- if (SenseData[2] == 0x06 && /* media changed */
- SenseData[7] >= 3 && /* enough sense data */
- SenseData[12] == 0x28) /* media changed */
- {
- Delay(10);
- return CD_ReadTOC();
- }
- return 0;
- }
-
- BOOL
- IsCD_SCSI(void)
- {
- static SCSICMD6 command = { SCSI_INQUIRY };
-
- /* Test if a SCSI target is a CD-ROM device */
-
- command.b4 = 40;
-
- if (!DoSCSI( DataBuf, DATA_LEN, &command, sizeof(command), (SCSIF_READ|SCSIF_AUTOSENSE) ))
- {
- return (BOOL)(((DataBuf[0] & 0x1f) == 0x05) ? TRUE : FALSE); /* is a CD-ROM */
- }
- return FALSE;
- }
-